﻿namespace JoinBox.Forms;

using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Xml.Linq;

using System.Windows.Forms;
using CheckBox = System.Windows.Forms.CheckBox;
using Control = System.Windows.Forms.Control;
using GroupBox = System.Windows.Forms.GroupBox;
using KeyEventArgs = System.Windows.Forms.KeyEventArgs;
using ListBox = System.Windows.Forms.ListBox;
using ListView = System.Windows.Forms.ListView;
using ListViewItem = System.Windows.Forms.ListViewItem;
using MouseEventArgs = System.Windows.Forms.MouseEventArgs;
using RadioButton = System.Windows.Forms.RadioButton;
using TextBox = System.Windows.Forms.TextBox;

public static class FormHelper
{
    // https://blog.csdn.net/jasonhongcn/article/details/84869041
    /// <summary>
    /// 表格双缓冲
    /// </summary>
    /// <param name="dgv"></param>
    /// <param name="flag"></param>
    public static void DoubleBufferedDataGirdView(this DataGridView dgv, bool flag)
    {
        var dgvType = dgv.GetType();
        var pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
        pi?.SetValue(dgv, flag, null);
    }

    /// <summary>
    /// 双缓冲,解决闪烁问题
    /// </summary>
    /// <param name="lv"></param>
    /// <param name="flag"></param>
    public static void DoubleBufferedListView(this ListView lv, bool flag)
    {
        var lvType = lv.GetType();
        var pi = lvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
        pi?.SetValue(lv, flag, null!);
    }

    public static List<T> ToList<T>(this ListBox listBox)
    {
        var obj = new List<T>();
        foreach (T item in listBox.Items)
            obj.Add(item);
        return obj;
    }

    /// <summary>
    /// 删除listbox某几行内容,返回
    /// </summary>
    /// <param name="listBox"></param>
    /// <returns>哪几行被删除了</returns>
    public static int[] DelItem(this ListBox listBox)
    {
        var re = new List<int>();// 将所有选择的记录下来

        int selIndex = -1;
        // 如果listbox是多选的,循环删除
        while (listBox.SelectedIndex != -1)
        {
            selIndex = listBox.SelectedIndex; // 选中项目索引
            listBox.Items.RemoveAt(selIndex); // 不断删除选中的第一个
            re.Add(selIndex);
        }
        int itemCount = listBox.Items.Count;  // 项目数
        // 选中删除后的前一项
        if (itemCount > selIndex)
            listBox.SelectedIndex = selIndex;
        else
            listBox.SelectedIndex = selIndex - 1;
        return re.ToArray();
    }

    /// <summary>
    /// 删除listbox所有内容
    /// </summary>
    /// <param name="listBox"></param>
    public static void DelItemAll(this ListBox listBox)
    {
        while (listBox.Items.Count != 0)
            listBox.Items.RemoveAt(listBox.Items.Count - 1); // 删除选中项目
    }
    /// <summary>
    /// 判断string的是路径还是文件,将内容加入listbox
    /// </summary>
    /// <param name="path"></param>
    /// <param name="listBox"></param>
    public static void StringisPathOrFile(string? path, ListBox? listBox)
    {
        if (path is null)
            throw new ArgumentNullException(nameof(path));
        if (listBox is null)
            throw new ArgumentNullException(nameof(listBox));

        List<string> ls = new();

        if (Directory.Exists(path))
        {
            DirectoryInfo dir = new(path);
            var fil = dir.GetFiles();
            for (int i = 0; i < fil.Length; i++)
                ls.Add(fil[i].FullName);
        }
        else if (File.Exists(path))
            ls.Add(path);

        // 先获取这个框内有没有相同的,再加入
        foreach (string item in ls)
        {
            bool flag = true;
            // 遍历listBox1中的每一项,赋值给数组
            for (int i = 0; i < listBox.Items.Count; i++)
            {
                if (item == listBox.Items[i].ToString())
                {
                    flag = false;
                    break;
                }
            }
            if (flag)
                listBox.Items.Add(item); // 一定要遍历完所有之后没有再加入
        }
    }

    /// <summary>
    /// 获取文本框触发的回车
    /// </summary>
    /// <param name="e">传到的数据</param>
    /// <param name="text">路径或文件</param>
    /// <param name="listBox">把要路径或文件的内容列表写到这个ListBox</param>
    public static void GetEnterKey(KeyEventArgs? e, string? text, ListBox? listBox)
    {
        if (e?.KeyCode == Keys.Control || e?.KeyCode == Keys.Enter)
            StringisPathOrFile(text, listBox);
    }


    /// <summary>
    /// 加入内容到listbox
    /// </summary>
    /// <param name="path">路径视表</param>
    /// <param name="TxtViw">文本视表</param>
    // public static string? PathViwToTxtViw(string path, ListBox TxtViw)
    // {
    //    if (!File.Exists(path))
    //        return null;

    //    // 清空listBox,再导入
    //    DelItemAll(TxtViw);

    //    var lines = BasalCurrency.FileHelper.ReadAllLines(path);
    //    for (int i = 0; i < lines.Length; i++)
    //        TxtViw.Items.Add(lines[i]);
    //    if (TxtViw.Items.Count > -1)   // 打开文件的内容行
    //        TxtViw.SelectedIndex = 0;  // 选中行
    //    return path;
    // }

    /// <summary>
    /// 禁止输入数字外的东西
    /// </summary>
    public static void ProhibitionNonNumeric(KeyPressEventArgs? e, TextBox? textbox)
    {
        if (e is null || textbox is null)
            return;

        if ((e.KeyChar < 48 || e.KeyChar > 57) && e.KeyChar != 8 && e.KeyChar != 46)
            e.Handled = true;

        // 小数点的处理
        if (e.KeyChar == 46) // 小数点
        {
            if (textbox.Text.Length < 1)
            {
                e.Handled = true;   // 小数点不能在第一位
                return;
            }

            if (!float.TryParse(textbox.Text + e.KeyChar.ToString(), out _))
                e.Handled = float.TryParse(textbox.Text, out _);
        }
    }



    /// <summary>
    /// 左键执行委托的函数,右键打开文件夹
    /// </summary>
    /// <param name="e">鼠标事件</param>
    /// <param name="filePath">文件路径</param>
    /// <param name="voidEvent">左键的委托</param>
    public static void OpendFile(this MouseEventArgs e,
                                 Action<object[]> voidEvent,
                                 string filePath,
                                 params object[] obj)
    {
        if (!File.Exists(filePath))
            return;

        if (e.Button == MouseButtons.Left) // 左键执行委托的函数
        {
            var lst = new List<object>
            {
                filePath
            };
            lst.AddRange(obj);
            voidEvent(obj);
        }
        else if (e.Button == MouseButtons.Right)// 右键 打开文件夹
        {
            // 打开选中的文件夹并指向选中的文件
            Process.Start("explorer.exe", "/select,\"" + filePath + "\"");
        }
    }


    /// <summary>
    /// 递归获取所有控件
    /// </summary>
    /// <param name="fatherControl">控件,来自与所有控件 this.Control.ControlCollection</param>
    public static void GetAllControls(Control fatherControl, List<Control> conts)
    {
        foreach (Control control in fatherControl.Controls)
        {
            conts.Add(control);
            if (control.Controls is not null)
                GetAllControls(control, conts);
        }
    }

    /// <summary>
    /// 获取组内的单选按钮名称
    /// </summary>
    /// <param name="gb"></param>
    /// <returns></returns>
    public static string? GetRadioButtonText(this GroupBox gb)
    {
        return GetRadioButtonText(gb.Controls);
    }

    /// <summary>
    /// 获取控件集合的单选按钮名称
    /// </summary>
    /// <param name="controls"></param>
    /// <returns></returns>
    public static string? GetRadioButtonText(this Control.ControlCollection controls)
    {
        foreach (Control control in controls)// 遍历控件集合
            if (control is RadioButton ra && ra.Checked)// 选中了这个按钮
                return ra.Text;
        return null;
    }

    /// <summary>
    /// 重排 ListView 序号
    /// </summary>
    /// <param name="listView"></param>
    public static void ListViewPaiXu(ListView listView)
    {
        var a = 0;
        foreach (ListViewItem lvi in listView.Items)
        {
            if (lvi.SubItems.Count < 1)
                continue;
            lvi.SubItems[0].Text = (++a).ToString();
        }
    }

    public static void ListView1_KeyDown_Del(this ListView listView, Action<ListViewItem> feedback)
    {
        foreach (ListViewItem lvi in listView.SelectedItems)// 选中项遍历
        {
            feedback.Invoke(lvi);
            // 要删除的话,移除当前状态的合并表
            listView.Items.RemoveAt(lvi.Index);
        }
    }

    public static void SetListView(this ListView listV, string newName, IEnumerable<string> layOldNames)
    {
        listV.BeginUpdate();  // 数据更新,UI暂时挂起,直到EndUpdate绘制控件,可以有效避免闪烁并大大提高加载速度
        int number = 0;
        foreach (var oldName in layOldNames)
        {
            var lvi = ListViewSubItem(number++, oldName, newName);

            // 判断表格中是否有相同元素,没有才加入
            bool chongfu = false;
            foreach (ListViewItem item in listV.Items)
            {
                if (lvi.SubItems.Count == item.SubItems.Count &&
                      lvi.SubItems.Count == 3 &&
                      lvi.SubItems[1].Text == item.SubItems[1].Text &&
                      lvi.SubItems[2].Text == item.SubItems[2].Text)
                {
                    chongfu = true;
                    break;
                }
            }
            if (!chongfu)
                listV.Items.Add(lvi);
        }
        listV.EndUpdate();  // 结束数据处理,UI界面一次性绘制.
    }

    public static ListViewItem ListViewSubItem(int num, params string[] str)
    {
        var lvi = new ListViewItem(num.ToString());
        foreach (var item in str)
            lvi.SubItems.Add(item);
        return lvi;
    }


    /// <summary>
    /// 打开配置xml,获取原有配置,设定控件-可选按钮
    /// </summary>
    /// <param name="configXmlPath">xml路径</param>
    /// <param name="superMergeName">节点</param>
    /// <param name="xiang">条项</param>
    /// <param name="controls">所有控件</param>
    /// <param name="CheckBoxName">可选按钮名称</param>
    public static void XmlSetCheckButton(string configXmlPath, string superMergeName, string xiang, Control.ControlCollection controls, string CheckBoxName)
    {
        if (!File.Exists(configXmlPath))// 可能会被删除
            return;

        var xdoc = XDocument.Load(configXmlPath); // 加载xml文件
        var root = xdoc.Root;                      // 获取根元素
        var xeles = root?.Elements();                    // 获取根元素下所有的直接子元素

        if (xeles == null)
            return;
        foreach (XElement xeleClass in xeles)
        {
            if (xeleClass.Name != superMergeName)
                continue;

            foreach (XElement item in xeleClass.Elements())
            {
                if (item.Name.ToString() != xiang)
                    continue;

                var conts = new List<Control>();
                // 遍历所有控件,找到 Check名称一样的
                foreach (Control control in controls)
                    GetAllControls(control, conts);

                foreach (var controlA in conts)
                {
                    if (controlA is CheckBox check &&
                        check.Text == CheckBoxName)// 如果名字一样(上次名称)
                    {
                        _ = bool.TryParse(item.Value, out bool res);
                        check.Checked = res;
                        break;
                    }
                }
            }
            break;
        }
    }

    /// <summary>
    /// 打开配置xml,获取原有配置,设定控件-单选按钮
    /// </summary>
    /// <param name="configXmlPath">xml路径</param>
    /// <param name="superMergeName">节点</param>
    /// <param name="xiang">条项</param>
    /// <param name="groupBox">面板的组</param>
    /// <param name="radioButtonName">找不到就挑选一个默认选择,单选按钮名称</param>
    public static void XmlSetRadioButton(string configXmlPath,
                                         string superMergeName,
                                         string xiang,
                                         GroupBox groupBox,
                                         string? radioButtonName = null)
    {
        if (!File.Exists(configXmlPath))// 可能会被删除
            return;

        var xdoc = XDocument.Load(configXmlPath); // 加载xml文件
        var root = xdoc.Root; // 获取根元素
        var xeles = root?.Elements(); // 获取根元素下所有的直接子元素
        if (xeles == null)
            return;

        XElement? xele = null;
        foreach (XElement? xeleClass in xeles)
        {
            if (xeleClass.Name != superMergeName)
                continue;
            xele = xeleClass;
            break;
        }

        if (xele == null)
            return;

        foreach (var item in xele.Elements())
        {
            if (item.Name.ToString() != xiang)
                continue;

            RadioButton? button = null;
            foreach (var con in groupBox.Controls)// 遍历控件集合 Controls Control
            {
                if (con is RadioButton ra && ra.Text == item.Value)// 如果名字一样(上次名称)
                {
                    button = ra;
                    break;
                }
            }

            if (button is not null) // 有上次选中
            {
                button.Checked = true; // 选中这个按钮
                continue;
            }

            if (!string.IsNullOrEmpty(radioButtonName?.Trim()))
                continue;

            foreach (Control con in groupBox.Controls)// 遍历控件集合 Controls
                if (con is RadioButton ra && ra.Text == radioButtonName)
                {
                    button = ra;
                    break;
                }

            if (button is not null) // 有默认名
            {
                button.Checked = true; // 选中这个按钮
            }
            else // 没有默认名,随机选择
            {
                foreach (var con in groupBox.Controls)// 遍历控件集合 Controls Control
                    if (con is RadioButton ra)
                    {
                        ra.Checked = true;// 选中这个按钮
                        break;
                    }
            }
        }
    }
}
